#ifndef MATH_H
#define MATH_H

#include <cmath>
#include <cstdlib>

const static float PI    = 3.14159265358979323846f;
const static float PI2   = 6.283185307f;
const static float PI3_2 = 4.71238898f;
const static float PI1_2 = 1.570796327f;


#define ABS(n) (((n) < 0.0) ? -(n) : n)
#define BETWEEN(n,a,b) ((n) >= (a) && (n) <= (b))
#define MIN(x,y) ((x < y) ? x : y)
#define MAX(x,y) ((x > y) ? x : y)
#define SQUARE(E) ((E) * (E))
#define EPSILON 0.0002;

const static float PHI = 1.61803389f;
const static float phi = 0.61803389f;

class Math
{
public:

	static float DegreeToRadian(float DegAngle)
	{
		return(DegAngle * PI / 180.0f);
	}

	static float RadianToDegree(float RadAngle)
	{
		return(RadAngle * 180.0f / PI);
	}

// 	static int   Randomize(void)
// 	{
// 		static int LastRandom = 0;
// 		if (LastRandom == 0)
// 			srand((unsigned)time(NULL));
// 		int RandNum = (rand() + LastRandom) % RAND_MAX;
// 		LastRandom = RandNum;
// 		return(RandNum);
// 	}

// 	static float Random(void)
// 	{
// 		return(static_cast<float>(Randomize()) / (float)RAND_MAX);
// 	}

	static int RandomIntegerBetween( int min, int max )
	{
		if( max <= min ) return min;

		int val =  min + rand() % ( max - min + 1 );

		if( val > max )	val = max;

		return val;
	}

	static float Clamp(float value, float min, float max)
	{
		return (value < min ? min : ( value > max ? max: value));
	}

	static float Round(float value, int precision)
	{
		float alpha = value;
		int   beta = 1;

		for(int i=0;i<precision;i++)
			beta *= 10;

		alpha *= beta;

		alpha = floor(alpha);

		alpha /= beta;

		return alpha;
	}

	//static void Unproject(Vec3& Origin, Vec3& Direction, const Vec3& Position2D, const Matrix& ViewInverse, const Matrix& Projection, int ScreenWidth, int ScreenHeight);

	static float sqrtf(float a) { return sqrt(a); }

	static float powf(float a, int apow) { return pow(a,apow); }

	static float cosf (float aCos) { return cos(aCos); }
	static float sinf (float aSin) { return sin(aSin); }
	static float tanf (float aTan) { return tan(aTan); }
	static float atan2f (float aSin, float aS) { return atan2(aSin, aS); }
	static float acosf(float a) { return acos(a); }

	static float floor(float a) { return floor(a); }
};

#endif